MVC5, Web API 2 and Ninject
Asked Answered
M

8

72

I have created a new MVC5 project with Web API 2, I then added the Ninject.MVC3 package from NuGet.

Constructor injection is working fine for the MVC5 controllers, but i am getting an error when trying to use it with the Web API Controllers.

An error occurred when trying to create a controller of type 'UserProfileController'. Make sure that the controller has a parameterless public constructor.

Constructor for working MVC5 controller:

public class HomeController : Controller
{
    private IMailService _mail;
    private IRepository _repo;

    public HomeController(IMailService mail, IRepository repo)
    {
        _mail = mail;
        _repo = repo;
    }
}

Constructor for non-working Web API Controller:

public class UserProfileController : ApiController
{
    private IRepository _repo;

    public UserProfileController(IRepository repo)
    {
        _repo = repo;
    }
}

Below is the full NinjectWebCommon.cs file:

[assembly: WebActivator.PreApplicationStartMethod(typeof(DatingSite.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(DatingSite.App_Start.NinjectWebCommon), "Stop")]

namespace DatingSite.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;
using DatingSite.Services;
using DatingSite.Data;

public static class NinjectWebCommon
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
#if DEBUG
        kernel.Bind<IMailService>().To<MockMailService>().InRequestScope();

#else
        kernel.Bind<IMailService>().To<MailService>().InRequestScope();
#endif
        kernel.Bind<SiteContext>().To<SiteContext>().InRequestScope();
        kernel.Bind<IRepository>().To<Repository>().InRequestScope();
    }
}
}
Millda answered 15/12, 2013 at 14:13 Comment(4)
The message means that injection isn't registered correctly for WebAPI. I suspect something like this may be required for MVC5 too.Acescent
@JoachimIsaksson i Suspect the same thing, would you know what I need to do, to register this?Millda
@Millda ... Joachim's link tells you what needs to be done, the only difference I see in CreateKernel is that you do not have this line: GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);Ahn
@Declan, I believe you can help me with this issue if you have 30 secs... Thks a lot! #22401903Accalia
E
106

The Ninject.Web.WebApi NuGet package has just been released. From now on the preferred solution is using that package. I couldn't find any related documentation but after installing the package everything worked for me.

Install-Package Ninject.Web.WebApi 

After installation both the normal MVC and the API controller instances are provided by Ninject.

If you have Ninject.Web.Common already installed make sure to save your bindings from NinjectWebCommon.cs and let Nuget rewrite NinjectWebCommon.cs during install and put back your bindings when finished.

As pointed out in the comments depending on your execution context you will need one of the following packages as well:

  • Ninject.Web.WebApi.WebHost
  • Ninject.Web.WebApi.OwinHost
  • Ninject.Web.WebApi.Selfhost

The most common scenario is IIS for that pick the WebHost package.

In the case you start an IIS MVC5 web app from scratch and want to use Ninject install the following packages:

  • Ninject - Ninject core dll
  • Ninject.Web.Common - Common Web functionality for Ninject eg. InRequestScope()
  • Ninject.MVC5 - MVC dependency injectors eg. to provide Controllers for MVC
  • Ninject.Web.Common.WebHost - Registers the dependency injectors from Ninject.MVC5 when IIS starts the web app. If you are not using IIS you will need a different package, check above
  • Ninject.Web.WebApi WebApi dependency injectors eg. to provide Controllers for WebApi
  • Ninject.web.WebApi.WebHost - Registers the dependency injectors from Ninject.Web.WebApi when IIS starts the web app.
Exmoor answered 24/3, 2014 at 13:42 Comment(6)
To get this to play nicely with IIS I needed to install Ninject.Web.WebApi.WebHost. This provided WebActivatorEx and NinjectWebCommon which seems necessary for a fresh WebApi project.Zara
Can we use MVC website & WebAPI in same project?Polynomial
This did not prompt to overwrite any files when I installed the packages, however adding Ninject.Web.WebApi and Ninject.Web.WebApi.WebHost resolved the issue in my combined MVC + Web API application.Fanya
Don't forget to add GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); after RegisterServices(kernel);Ragtime
As of 7/13/2017, using WebApi2 and MVC5, this solution did not work for me. Per snippet on this page thisdevmind.com/2015/01/19/…. I uninstalled WebApi and WebApi.WebHost per recommendation, "rolled my own resolver" and was able to get everything working. I followed this guide: peterprovost.org/blog/2012/06/19/adding-ninject-to-web-apiAbelmosk
Install-Package Ninject.Web.WebApi not able to install. getting error I am using IDE VS2017Kasiekask
E
37

You have this problem because Controller and ApiController use different Dependency Resolvers. Solution is very simple.

At first create new classes of Dependency Resolver and Dependency Scope. You can use this:

 public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private readonly IKernel _kernel;
    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

public class NinjectScope : IDependencyScope
{
    protected IResolutionRoot resolutionRoot;
    public NinjectScope(IResolutionRoot kernel)
    {
        resolutionRoot = kernel;
    }
    public object GetService(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).SingleOrDefault();
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).ToList();
    }
    public void Dispose()
    {
        IDisposable disposable = (IDisposable)resolutionRoot;
        if (disposable != null) disposable.Dispose();
        resolutionRoot = null;
    }
}

After that, add next line to method CreateKernel() in NinjectWebCommon

 GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
Erinerina answered 15/1, 2014 at 16:4 Comment(4)
This answer explains which DependencyResolver to use and when (related to Ninject libraries being used) https://mcmap.net/q/275858/-mvc5-webapi2-and-ninject-parameterless-constructor-errorClarkclarke
I highly recommend using the nuget package that's out now. I had issues with code simililar to aboveGossipry
-1 as IActivationBlock is not the preferred way of doing so and will be soon removed (planetgeek.ch/2012/04/23/future-of-activation-blocks). Kindly update your solution. The problem that I faced while implementing above solution was all dependencies registered in SingletonScope were behaving as TransientScope. Here is another link: #26709479Erst
please update your answer with the note Above and I will remove -1Erst
E
29

I had the same problem. After installation of the following NuGet packages:

  • Ninject
  • Ninject.web.WebApi
  • Ninject.web.WebApi.WebHost
  • Ninject.MVC3
  • Ninject.web.Common
  • Ninject.web.Common.WebHost

everything works fine

Enrique answered 9/4, 2015 at 9:4 Comment(4)
+1 Thank!. I didn'it install "Ninject.web.WebApi.WebHost", and after you post i did it . Eveything is Ok now.Frigg
I also needed to add Ninject.web.WebApi.WebHost thanks for the assist!Quizmaster
Ninject.web.WebApi.WebHost creates all the files you need. You just need to write your implementation in the RegisterServices it provides. The other answers are confusing. This is the only thing you need to do.Arceliaarceneaux
This is the answer that also worked for me. However, I wonder why we need all those packages. Can anyone refer me to a link or tutorial that explains what is going on under the hood?Pink
S
24

I'm found that assembly Ninject.Web.WebApi.dll define own DependencyResolver and register it with kernel in class Ninject.Web.WebApi.WebApiModule automatically.

So I simply add to NinjectWebCommon.CreateKernel one line...

GlobalConfiguration.Configuration.DependencyResolver = 
    kernel.Get<System.Web.Http.Dependencies.IDependencyResolver>();

Finally my project has following dependencies:

  • Ninject 3.2.0
  • Ninject.Web.Common 3.2.0
  • Ninject.Web.WebApi 3.2.4
Spell answered 30/6, 2015 at 11:29 Comment(4)
Goshhh It works !!! Additionally , the GlobalConfiguration must have using System.Web.Http; namespace.Keri
simplest and best answerHolozoic
works for me, I added before "RegisterServices(kernel);" line, inside the try{} block. Thank you!Woolley
Thank you. You are awesome. I wasted couple hours. This wasn't needed in MVC project but needed in Web API.Jigger
S
3

Just for others, who might have a similar set up to me, and got here via google like I did.

I had multiple applications using one WebApi project. I would get the above error if I hadn't included the binding in the RegisterServices method. So before pulling your hair out, just check you have the binding set up. The error doesn't tell you you have missing bindings. Which it would if the Application is in the same project as the WebApi.

Silvas answered 4/3, 2015 at 21:28 Comment(1)
Getting the error 'Make sure that the controller has a parameterless public constructor.' is extremely misleading in this case. This answer worked for me after hours of trying all kinds of other stuff. Just a simple missing binding!Pontoon
I
3

I recently had to get Web Api 2 working with so I can answer that part of the question.

These are the nuget packages needed for Web Api 2-

Ninject
Ninject.Web.Common
Ninject.Web.Common.WebHost
Ninject.Web.WebApi 
WebActivatorEx 

Then edit NinjectWebCommon.CreateKernel(..) including

RegisterServices(kernel);
// the next line is the important one
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

I've written a more detailed post about this - http://NoDogmaBlog.bryanhogan.net/2016/04/web-api-2-and-ninject-how-to-make-them-work-together/ including a full solution to download.

Ingurgitate answered 22/4, 2016 at 6:35 Comment(0)
B
1

You are supposed to install these packages from Nuget in webAPI project.

  1. Ninject
  2. Ninject.Web.Common
  3. Ninject.Web.Common.WebHost
  4. Ninject.Web.WebApi
  5. Ninject.Web.WebApi.WebHost

Then you must install the Ninject package in the Repository project as well (the version must be the same as in API project). I had the same issue when there was a different version installed for Ninject.

Bonaparte answered 15/7, 2020 at 5:58 Comment(0)
R
0

I had this issue in a solution where the project in which I was using Ninject was not using Web API (I have 6 projects so far in my solution). I kept on getting the dreaded "parameterless constructor required" which obviously meant when I added it the Ninject injection was not getting instantiated as it was dropping into the empty constructor. I tried various solutions but in the end I checked my Ninject packages and saw that the Ninject.Web.Webapi package was installed. I uninstalled this and did a clean and rebuild. This solved the issue. My other lower level project was referencing the Ninject.Web.Api package and stupidly I had installed that into my Web front end project.

I hope this may help other people who have tried all the Stack solutions and got no where.

Resuscitator answered 19/4, 2018 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.